﻿
using Boilen.Freezables;
using Boilen.Primitives.CodeGeneration;
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;
using Xunit.Extensions;


namespace Boilen.Primitives.Implementers {

    public class TestNewDependencyProperty : TestImplementers {

        [Theory]
        [PropertyData( "SourceTypes" )]
        public void code_compiles_for_1_NewDependencyProperty( Type sourceType ) {
            var eci = MemberTestInfo.Create<int>( "state" );

            var pt = Partial.Type( sourceType )
                .AddDependencyProperty<int>( eci.ParameterName, eci.Description )
                ;
            var members = Compile.PartialType( pt );
        }

        [Theory]
        [PropertyData( "SourceTypes" )]
        public void code_compiles_for_1_NewDependencyProperty_with_attribute( Type sourceType ) {
            var eci = MemberTestInfo.Create<int>( "state" );

            var pt = Partial.Type( sourceType )
                .AddDependencyProperty<int>( eci.ParameterName, eci.Description, p => p
                    .AddAttribute( typeof( ObsoleteAttribute ), CompilationSymbol.NotSilverlight, new[] { TypeRepository.EscapeString( "This is obsolete." ), "false" } )
                )
                ;
            var members = Compile.PartialType( pt );
        }

        [Theory]
        [PropertyData( "SourceTypes" )]
        public void code_compiles_for_3_NewDependencyProperty_with_conditions( Type sourceType ) {
            var eci = MemberTestInfo.Create<int>( "state" );

            var pt = Partial.Type( sourceType )
                .AddDependencyProperty<int>( "None", eci.Description, p => p.SetCondition( CompilationSymbol.None ) )
                .AddDependencyProperty<int>( "NotSilverlight", eci.Description, p => p.SetCondition( CompilationSymbol.NotSilverlight ) )
                .AddDependencyProperty<int>( "Silverlight", eci.Description, p => p.SetCondition( CompilationSymbol.Silverlight ) )
                .AddDependencyProperty<int>( "Custom", eci.Description, p => p.SetCondition( new CompilationSymbol( "CUSTOM" ) ) )
                ;
            var members = Compile.PartialType( pt );
        }

        [Theory]
        [PropertyData( "SourceTypes" )]
        public void code_compiles_for_3_NewDependencyProperty_with_conditions_with_external_documentation( Type sourceType ) {
            var eci = MemberTestInfo.Create<int>( "state" );

            using( ChangeExternalDocumentationPrefix( ) ) {
                var pt = Partial.Type( sourceType )
                    .AddDependencyProperty<int>( "None", p => p.SetCondition( CompilationSymbol.None ) )
                    .AddDependencyProperty<int>( "NotSilverlight", p => p.SetCondition( CompilationSymbol.NotSilverlight ) )
                    .AddDependencyProperty<int>( "Silverlight", p => p.SetCondition( CompilationSymbol.Silverlight ) )
                    .AddDependencyProperty<int>( "Custom", p => p.SetCondition( new CompilationSymbol( "CUSTOM", false ) ) )
                    ;
                var members = Compile.PartialType( pt );
            }
        }

        [Theory]
        [PropertyData( "SourceTypes" )]
        public void code_compiles_for_1_NewDependencyProperty_with_category( Type sourceType ) {
            var eci = MemberTestInfo.Create<int>( "state" );

            var pt = Partial.Type( sourceType )
                .AddDependencyProperty<int>( eci.ParameterName, eci.Description, p => p
                    .SetCategory( "Behavior" )
                )
                ;
            var members = Compile.PartialType( pt );
        }

        [Theory]
        [PropertyData( "SourceTypes" )]
        public void code_compiles_for_1_Brush_NewDependencyProperty( Type sourceType ) {
            var eci = MemberTestInfo.Create<Brush>( "brush", Brushes.Red );

            var pt = Partial.Type( sourceType )
                .AddDependencyProperty<Brush>( eci.ParameterName, eci.Description, p => p
                    .SetDefaultValue( eci.DefaultValue )
                )
                ;
            var members = Compile.PartialType( pt );
        }

        [Theory]
        [PropertyData( "SourceTypes" )]
        public void code_compiles_for_1_Size_NewDependencyProperty( Type sourceType ) {
            var eci = MemberTestInfo.Create<Size>( "size", new Size( 5, double.NaN ) );

            var pt = Partial.Type( sourceType )
                .AddDependencyProperty<Size>( eci.ParameterName, eci.Description, p => p
                    .SetDefaultValue( eci.DefaultValue )
                )
                ;
            var members = Compile.PartialType( pt );
        }

        [Theory]
        [PropertyData( "SourceTypes" )]
        public void code_compiles_for_1_double_NewDependencyProperty( Type sourceType ) {
            var eci = MemberTestInfo.Create<double>( "vaule", double.NaN );

            var pt = Partial.Type( sourceType )
                .AddDependencyProperty<double>( eci.ParameterName, eci.Description, p => p
                    .SetDefaultValue( eci.DefaultValue )
                )
                ;
            var members = Compile.PartialType( pt );
        }

        [Theory]
        [PropertyData( "SourceTypes" )]
        public void code_compiles_for_1_attached_NewDependencyProperty( Type sourceType ) {
            var eci = MemberTestInfo.Create<int>( "state" );

            var pt = Partial.Type( sourceType )
                .AddDependencyProperty<int>( eci.ParameterName, eci.Description, p => p
                    .SetAttached( typeof( DependencyObject ) )
                )
                ;
            var members = Compile.PartialType( pt );
        }

        [Theory]
        [PropertyData( "SourceTypes" )]
        public void code_compiles_for_1_freezable_NewDependencyProperty( Type sourceType ) {
            var eci = MemberTestInfo.Create<FreezableImpl>( "state" );

            var pt = Partial.Type( sourceType )
                .AddDependencyProperty<FreezableImpl>( eci.ParameterName, eci.Description, p => p
                    .SetDefaultExpression( "new FreezableImpl()" )
                )
                ;
            var members = Compile.PartialType( pt );
        }

        [Theory]
        [PropertyData( "SourceTypes" )]
        public void code_compiles_for_1_readonly_NewDependencyProperty( Type sourceType ) {
            var eci = MemberTestInfo.Create<int>( "state" );

            var pt = Partial.Type( sourceType )
                .AddDependencyProperty<int>( eci.ParameterName, eci.Description, p => p
                    .SetSetterAccessibility( Accessibility.Protected )
                    .SetDefaultExpression( "new int()" )
                )
                ;
            var members = Compile.PartialType( pt );
        }

        [Theory]
        [PropertyData( "SourceTypes" )]
        public void code_compiles_for_1_readonly_NewDependencyProperty_with_external_documentation( Type sourceType ) {
            var eci = MemberTestInfo.Create<int>( "state" );

            using( ChangeExternalDocumentationPrefix( ) ) {
                var pt = Partial.Type( sourceType )
                    .AddDependencyProperty<int>( eci.ParameterName, p => p
                        .SetSetterAccessibility( Accessibility.Protected )
                        .SetDefaultExpression( "new int()" )
                    )
                    ;
                var members = Compile.PartialType( pt );
            }
        }

        [Theory]
        [PropertyData( "SourceTypes" )]
        public void code_compiles_for_1_private_NewDependencyProperty( Type sourceType ) {
            var eci = MemberTestInfo.Create<int>( "state" );

            var pt = Partial.Type( sourceType )
                .AddDependencyProperty<int>( eci.ParameterName, eci.Description, p => p
                    .SetAccessibility( Accessibility.Private )
                )
                ;
            var members = Compile.PartialType( pt );
        }

        [Theory]
        [PropertyData( "SourceTypes" )]
        public void code_compiles_for_1_private_attached_NewDependencyProperty( Type sourceType ) {
            var eci = MemberTestInfo.Create<int>( "state" );

            var pt = Partial.Type( sourceType )
                .AddDependencyProperty<int>( eci.ParameterName, eci.Description, p => p
                    .SetAttached( true )
                    .SetAccessibility( Accessibility.Private )
                )
                ;
            var members = Compile.PartialType( pt );
        }

        [Theory]
        [InlineData( typeof( SourceDependencyObject ) )]
        public void code_compiles_for_1_NewDependencyProperty_with_SL_metadata_override( Type sourceType ) {
            var eci = MemberTestInfo.Create<int>( "override" );

            var pt = Partial.Type( sourceType )
                .AddDependencyProperty<int>( eci.ParameterName, eci.Description, p => p
                    .SetOptions( FrameworkPropertyMetadataOptions.AffectsParentMeasure, "CustomChangedHandler" )
                )
                ;
            var members = Compile.PartialType( pt );
        }

        [Theory]
        [PropertyData( "SourceTypes" )]
        public void code_compiles_for_1_NewDependencyProperty_with_standard_callbacks( Type sourceType ) {
            var eci = MemberTestInfo.Create<int>( "standardCallbacks" );

            var pt = Partial.Type( sourceType )
                .AddDependencyProperty<int>( eci.ParameterName, eci.Description, p => p
                    .SetOptions( FrameworkPropertyMetadataOptions.AffectsArrange )
                    .SetCoerce( Coerce.NonNegative )
                    .SetValidate( Validate.Enum )
                )
                ;
            var members = Compile.PartialType( pt );
        }

        [Theory]
        [PropertyData( "SourceTypes" )]
        public void code_compiles_for_1_NewDependencyProperty_with_custom_callbacks( Type sourceType ) {
            var eci = MemberTestInfo.Create<int>( "customCallbacks" );

            var pt = Partial.Type( sourceType )
                .AddDependencyProperty<int>( eci.ParameterName, eci.Description, p => p
                    .SetChanged( "CustomChangedHandler" )
                    .SetCoerce( "DependencyPropertyCallbacks.ExternalCoerceHandler" )
                    .SetValidate( "CustomValidateHandler" )
                )
                ;
            var members = Compile.PartialType( pt );
        }

        [Theory]
        [PropertyData( "SourceTypes" )]
        public void code_compiles_for_1_NewDependencyProperty_with_virtual_Changed_callback( Type sourceType ) {
            var eci = MemberTestInfo.Create<int>( "virtualCallbacks" );

            var pt = Partial.Type( sourceType )
                .AddDependencyProperty<int>( eci.ParameterName, eci.Description, p => p
                    .SetChanged( Changed.Virtual )
                )
                ;
            var members = Compile.PartialType( pt );
        }

        [Theory]
        [PropertyData( "SourceTypes" )]
        public void code_compiles_for_1_NewDependencyProperty_with_instance_Changed_callback( Type sourceType ) {
            var eci = MemberTestInfo.Create<int>( "customCallbacks" );

            var pt = Partial.Type( sourceType )
                .AddDependencyProperty<int>( eci.ParameterName, eci.Description, p => p
                    .SetChanged( Changed.Instance )
                )
                ;
            var members = Compile.PartialType( pt );
        }

        [Theory]
        [PropertyData( "SourceTypes" )]
        public void code_compiles_for_1_NewDependencyProperty_with_parameterless_Changed_callback( Type sourceType ) {
            var eci = MemberTestInfo.Create<int>( "customCallbacks" );

            var pt = Partial.Type( sourceType )
                .AddDependencyProperty<int>( eci.ParameterName, eci.Description, p => p
                    .SetChanged( Changed.Parameterless )
                )
                ;
            var members = Compile.PartialType( pt );
        }

        [Theory]
        [InlineData( typeof( SourceDependencyObject ) )]
        public void code_compiles_for_1_attached_NewDependencyProperty_with_SL_metadata_override( Type sourceType ) {
            var eci = MemberTestInfo.Create<int>( "override" );

            var pt = Partial.Type( sourceType )
                .AddDependencyProperty<int>( eci.ParameterName, eci.Description, p => p
                    .SetAttached( true )
                    .SetOptions( FrameworkPropertyMetadataOptions.Inherits, "CustomChangedHandler" )
                )
                ;
            var members = Compile.PartialType( pt );
        }

        [Theory]
        [PropertyData( "SourceTypes" )]
        public void code_compiles_for_1_attached_NewDependencyProperty_with_standard_callbacks( Type sourceType ) {
            var eci = MemberTestInfo.Create<int>( "standardCallbacks" );

            var pt = Partial.Type( sourceType )
                .AddDependencyProperty<int>( eci.ParameterName, eci.Description, p => p
                    .SetAttached( true )
                    .SetOptions( FrameworkPropertyMetadataOptions.AffectsArrange )
                    .SetCoerce( Coerce.NonNegative )
                    .SetValidate( Validate.Enum )
                )
                ;
            var members = Compile.PartialType( pt );
        }

        [Theory]
        [PropertyData( "SourceTypes" )]
        public void code_compiles_for_1_attached_NewDependencyProperty_with_standard_callbacks_with_external_documentation( Type sourceType ) {
            var eci = MemberTestInfo.Create<int>( "standardCallbacks" );

            using( ChangeExternalDocumentationPrefix( ) ) {
                var pt = Partial.Type( sourceType )
                    .AddDependencyProperty<int>( eci.ParameterName, p => p
                        .SetAttached( true )
                        .SetOptions( FrameworkPropertyMetadataOptions.AffectsArrange )
                        .SetCoerce( Coerce.NonNegative )
                        .SetValidate( Validate.Enum )
                    )
                    ;
                var members = Compile.PartialType( pt );
            }
        }

        [Theory]
        [PropertyData( "SourceTypes" )]
        public void code_compiles_for_1_attached_NewDependencyProperty_with_custom_callbacks( Type sourceType ) {
            var eci = MemberTestInfo.Create<int>( "customCallbacks" );

            var pt = Partial.Type( sourceType )
                .AddDependencyProperty<int>( eci.ParameterName, eci.Description, p => p
                    .SetAttached( true )
                    .SetChanged( "CustomChangedHandler" )
                    .SetCoerce( "CustomCoerceHandler" )
                    .SetValidate( "CustomValidateHandler" )
                )
                ;
            var members = Compile.PartialType( pt );
        }

        [Theory]
        [PropertyData( "SourceTypes" )]
        public void code_compiles_for_1_freezable_NewDependencyProperty_with_standard_callbacks( Type sourceType ) {
            var eci = MemberTestInfo.Create<FreezableImpl>( "standardCallbacks" );

            var pt = Partial.Type( sourceType )
                .AddDependencyProperty<FreezableImpl>( eci.ParameterName, eci.Description, p => p
                    .SetOptions( FrameworkPropertyMetadataOptions.AffectsArrange )
                    .SetCoerce( Coerce.NonNegative )
                    .SetValidate( Validate.NotNull )
                    .SetDefaultExpression( "new FreezableImpl()" )
                )
                ;
            var members = Compile.PartialType( pt );
        }

        [Theory]
        [PropertyData( "SourceTypes" )]
        public void code_compiles_for_1_freezable_NewDependencyProperty_with_custom_callbacks( Type sourceType ) {
            var eci = MemberTestInfo.Create<FreezableImpl>( "customCallbacks" );

            var pt = Partial.Type( sourceType )
                .AddDependencyProperty<FreezableImpl>( eci.ParameterName, eci.Description, p => p
                    .SetChanged( "CustomChangedHandler" )
                    .SetCoerce( "CustomCoerceHandler" )
                    .SetValidate( "CustomValidateHandler" )
                    .SetDefaultExpression( "new FreezableImpl()" )
                )
                ;
            var members = Compile.PartialType( pt );
        }

        [Theory]
        [PropertyData( "SourceTypes" )]
        public void code_compiles_for_1_freezable_NewDependencyProperty_with_virtual_Changed_callback( Type sourceType ) {
            var eci = MemberTestInfo.Create<FreezableImpl>( "virtualCallbacks" );

            var pt = Partial.Type( sourceType )
                .AddDependencyProperty<FreezableImpl>( eci.ParameterName, eci.Description, p => p
                    .SetChanged( Changed.Virtual )
                    .SetDefaultExpression( "new FreezableImpl()" )
                )
                ;
            var members = Compile.PartialType( pt );
        }

        [Theory]
        [PropertyData( "SourceTypes" )]
        public void code_compiles_for_1_freezable_NewDependencyProperty_with_instance_Changed_callback( Type sourceType ) {
            var eci = MemberTestInfo.Create<FreezableImpl>( "customCallbacks" );

            var pt = Partial.Type( sourceType )
                .AddDependencyProperty<FreezableImpl>( eci.ParameterName, eci.Description, p => p
                    .SetChanged( Changed.Instance )
                    .SetDefaultExpression( "new FreezableImpl()" )
                )
                ;
            var members = Compile.PartialType( pt );
        }

        [Theory]
        [PropertyData( "SourceTypes" )]
        public void code_compiles_for_1_freezable_NewDependencyProperty_with_parameterless_Changed_callback( Type sourceType ) {
            var eci = MemberTestInfo.Create<FreezableImpl>( "customCallbacks" );

            var pt = Partial.Type( sourceType )
                .AddDependencyProperty<FreezableImpl>( eci.ParameterName, eci.Description, p => p
                    .SetChanged( Changed.Parameterless )
                    .SetDefaultExpression( "new FreezableImpl()" )
                )
                ;
            var members = Compile.PartialType( pt );
        }


        public static IEnumerable<object[]> SourceTypes {
            get {
                yield return new object[] { typeof( SourceDependencyObject ) };
                yield return new object[] { typeof( SourceGenericDependencyObject<> ) };
                yield return new object[] { typeof( SourceFreezable ) };
            }
        }

    }

}
